--
-- Author: shineflag
-- Date: 2017-02-15 16:44:04
--

local skynet = require "skynet"
local hall = require("hall")
local log = require("log")

local server = {}
local users = {}  --完成登录的玩家

local idle_agent = {}  --空闲的agent

local ustatus = {
	online = 1,       --在线
	disconnect = 2,   --掉线
}

local CMD = {}

local function get_idle_agent()
	local agent
	if #idle_agent > 0 then 
		agent = table.remove(idle_agent,1)
	else
		agent = skynet.newservice "useragent"
	end

	return agent
end

function CMD.socket_close(mid)
	local u = users[mid]
	if u then
		hall.socket_close(mid)
	else
		log.d(TAG,"socket_close but user[%d] not login",mid)
	end
end

-- call by agent
function CMD.push(mid, data)
	local u = users[mid]
	if u then
		return hall.send(mid, data)
	else
		log.e(TAG,"user[%d] not login",mid)
	end
	return false
end

--客户端握手成功
function server.shake_ok(mid, secret)
	local agent 
	if users[mid] then
		log.e(TAG,"%s is already login", mid)
		agent = users[mid].agent
	else
		-- you can use a pool to alloc new agent
		agent = get_idle_agent()
		local ok, flag = pcall(skynet.call,agent, "lua", "login", mid,secret)
		if ok and flag then 
			local u = {
				mid = mid,
				agent = agent,
				status = ustatus.online,
			}

			users[mid] = u
		else
			table.insert(idle_agent,agent)
			hall.logout(mid)
		end
	end

	return agent
end

-- call by agent
function server.logout_handler(mid)
	log.d(TAG,"user[%d] logout and clear",mid)
	local u = users[mid]
	if u then
		hall.logout(mid)
		users[mid] = nil
		table.insert(idle_agent, u.agent)
		--skynet.call(logind, "lua", "logout",mid)
	else
		log.d(TAG,"user[%d] not login",mid)
	end
end

-- call by login server
function server.kick_handler(mid)
	local u = users[mid]
	if u then
		-- NOTICE: logout may call skynet.exit, so you should use pcall.
		log.e(TAG,"user %d kicked",mid)
		pcall(skynet.call, u.agent, "lua", "logout")
	end
end


-- call by self (when socket disconnect)
function server.disconnect_handler(mid)
	local u = users[mid]
	if u then
		u.status = ustatus.disconnect,
		skynet.call(u.agent, "lua", "afk")
	end
end

-- call by self (when recv a request from client)
function server.request_handler(mid, msg )
	local u = users[mid]
	if u then
		if #msg ~= 20 then  --not heart beat
			log.d(TAG,"user[%d] request msg sz[%d]",mid, #msg)
		end

		local resp =  skynet.tostring(skynet.rawcall(u.agent, "client", msg))
		return resp
	else
		error("user[%s] not login", mid)
	end
end



-- call by self (when gate open) 需要通知到 loginsever 供分配 
function server.register_handler(name,addr)

end

server.command = CMD

hall.start(server)